/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

package br.ufmg.dees.insane.analysisModel;
import java.io.Serializable;
import java.util.ArrayList;

import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.geometricProperties.GeometricProperties;
import br.ufmg.dees.insane.util.pointValues.PointValues;
import br.ufmg.dees.insane.util.pointValues.StringPointValues;

/** A class representing TimoSpaceFrame
 * @author CENOURA!!!
 * @since 31/05/2005
 */
public class TimoSpaceFrame implements AnalysisModel, Serializable {
	
	private static final long serialVersionUID = 1L;

	/**Constructs a TimoSpaceFrame Analysis Model and sets its label.*/
    public TimoSpaceFrame()
	{
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c) {
        double jac = this.getJacobianTransformation(d,c);
        IMatrix B = new IMatrix(6,6*d.getNumCol());
        B.setZero();
    	for(int i=0; i<d.getNumCol(); i++){
        B.setElement(0,6*i,d.getElement(0,i)*(1.0/jac));
        B.setElement(1,6*i+1,d.getElement(0,i)*(1.0/jac));
        B.setElement(1,6*i+5,-n.getElement(i));
        B.setElement(2,6*i+2,d.getElement(0,i)*(1.0/jac));
        B.setElement(2,6*i+4,n.getElement(i));
        B.setElement(3,6*i+3,d.getElement(0,i)*(1.0/jac));
        B.setElement(4,6*i+4,d.getElement(0,i)*(1.0/jac));
        B.setElement(5,6*i+5,d.getElement(0,i)*(1.0/jac));
    	}
         return B;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariableOperator(IMatrix d, IMatrix d2, IVector n, IMatrix c,
            IMatrix u) {
        d.setScale((1.0/this.getJacobianTransformation(d,c)));
        IMatrix B = new IMatrix(6,6*d.getNumCol());
        B.setZero();
        for(int i=0; i<d.getNumCol(); i++){
        B.setElement(0,6*i,d.getElement(0,i));
        B.setElement(1,6*i+1,d.getElement(0,i));
        B.setElement(1,6*i+5,-n.getElement(i));
        B.setElement(2,6*i+2,d.getElement(0,i));
        B.setElement(2,6*i+4,n.getElement(i));
        B.setElement(3,6*i+3,d.getElement(0,i));
        B.setElement(4,6*i+4,d.getElement(0,i));
        B.setElement(5,6*i+5,d.getElement(0,i));
        }
         return B;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDualInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getDualInternalVariableOperator(IMatrix e) {
    	IMatrix D = new IMatrix(6,6);
        D.setZero();
        D.setElement(0,0,e.getElement(0,0));
        D.setElement(1,1,e.getElement(3,3));
        D.setElement(2,2,e.getElement(4,4));
        D.setElement(3,3,e.getElement(5,5));
        D.setElement(4,4,e.getElement(1,1));
        D.setElement(5,5,e.getElement(2,2));
        return D;
    }
    
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#modifyDualInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, java.util.ArrayList)
     */
	public IMatrix modifyDualInternalVariableOperator(IMatrix e, GeometricProperties gps)	{
		e.setElement(0,0,e.getElement(0,0)*gps.getArea());
		e.setElement(1,1,e.getElement(1,1)*gps.getArea());
		e.setElement(2,2,e.getElement(2,2)*gps.getArea());
		e.setElement(3,3,e.getElement(3,3)*gps.getInertiaX());
		e.setElement(4,4,e.getElement(4,4)*gps.getInertiaY());
		e.setElement(5,5,e.getElement(5,5)*gps.getInertiaZ());
		return e;
	}
	
	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#modifyDualInternalVariableVector(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.geometricProperties.GeometricProperties)
	 */
	public IVector modifyDualInternalVariableVector(IVector s, GeometricProperties gps) {
		s.setElement(0,s.getElement(0)*gps.getArea());
		s.setElement(1,s.getElement(1)*gps.getArea());
		s.setElement(2,s.getElement(2)*gps.getArea());
		s.setElement(3,s.getElement(3)*gps.getInertiaX());
		s.setElement(4,s.getElement(4)*gps.getInertiaY());
		s.setElement(5,s.getElement(5)*gps.getInertiaZ());
		return s;
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getShapeMatrix(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix getStateVariableOperator(IMatrix d, IVector n, IMatrix c) {
    	IMatrix N = new IMatrix(6,6*n.getSize());
        N.setZero();
    	for(int i=0; i<n.getSize(); i++){
        N.setElement(0,6*i,n.getElement(i));
        N.setElement(1,6*i+1,n.getElement(i));
        N.setElement(2,6*i+2,n.getElement(i));
        N.setElement(3,6*i+3,n.getElement(i));
        N.setElement(4,6*i+4,n.getElement(i));
        N.setElement(5,6*i+5,n.getElement(i));
    	}
        return N;
    }
    
    /* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getGeometricOperator(br.ufmg.dees.insane.util.IVector)
	 */
	public IMatrix getGeometricOperator(IVector n1) {
		IMatrix G = new IMatrix(3,3*n1.getSize());
        G.setZero();
    	for(int i=0; i<n1.getSize(); i++){
        G.setElement(0,3*i,n1.getElement(i));
        G.setElement(1,3*i+1,n1.getElement(i));
        G.setElement(2,3*i+2,n1.getElement(i));
    	}
        return G;
	}
	
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfInternalVariables()
     */
    public int getNumberOfInternalVariables() {
        return 6;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getNumberOfDualInternalVariables()
     */
    public int getNumberOfDualInternalVariables() {
        return 6;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariablesTensor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getInternalVariablesTensor(IVector a, IMatrix b) {
    	 IMatrix chiTensor = new IMatrix(3,3);
         chiTensor.setZero();
    	 chiTensor.setElement(0,0,a.getElement(3));
    	 chiTensor.setElement(0,1,a.getElement(0));
    	 chiTensor.setElement(0,2,a.getElement(1));
    	 chiTensor.setElement(1,0,a.getElement(0));
    	 chiTensor.setElement(1,1,a.getElement(4));
    	 chiTensor.setElement(1,2,a.getElement(2));
    	 chiTensor.setElement(2,0,a.getElement(1));
    	 chiTensor.setElement(2,1,a.getElement(2));
    	 chiTensor.setElement(2,2,a.getElement(5));
         return chiTensor; 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalDualVariablesTensor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public IMatrix getDualInternalVariablesTensor(IVector a, IMatrix b) {
   	 	return expandTensor(a); 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalVariablesDirLabels()
     */
    public String[] getInternalVariablesLabels() {
    	String[] Dlabels = {"Ea", "GAMAy", "GAMAz", "PSIx", "Ky", "Kz"};
        return Dlabels;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getInternalDualVariablesDirLabels()
     */
    public String[] getDualInternalVariablesLabels() {
    	String[] Dlabels = {"Nx", "Vy", "Vz", "Tx", "My", "Mz"};
        return Dlabels;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#expandVector(br.ufmg.dees.insane.util.IVector)
     */
    public IVector expandVector(IVector a) {
        return a;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#expandTensor(br.ufmg.dees.insane.util.IVector)
     */
    public IMatrix expandTensor(IVector a) {
        IMatrix Tensor = new IMatrix(3,3);
        Tensor.setZero();
    	Tensor.setElement(0,0,a.getElement(3));
    	Tensor.setElement(0,1,a.getElement(0));
    	Tensor.setElement(0,2,a.getElement(1));
    	Tensor.setElement(1,0,a.getElement(0));
    	Tensor.setElement(1,1,a.getElement(4));
    	Tensor.setElement(1,2,a.getElement(2));
    	Tensor.setElement(2,0,a.getElement(1));
    	Tensor.setElement(2,1,a.getElement(2));
    	Tensor.setElement(2,2,a.getElement(5));
   	 	return Tensor; 
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#reduceVector(br.ufmg.dees.insane.util.IVector)
     */
    public IVector reduceVector(IVector a) {
        return a;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#reduceTensor(br.ufmg.dees.insane.util.IMatrix)
     */
    public IVector reduceTensor(IMatrix a) {
        IVector Vector = new IVector(6);
        Vector.zero();
        Vector.setElement(0,a.getElement(0,1));
        Vector.setElement(1,a.getElement(0,2));
        Vector.setElement(2,a.getElement(1,2));
        Vector.setElement(3,a.getElement(0,0));
        Vector.setElement(4,a.getElement(1,1));
        Vector.setElement(5,a.getElement(2,2));
        return Vector;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getType()
     */
    public String getLabel() {
        return "TimoshenkoSpaceFrame";
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getIntegrationFactor(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public double getIntegrationFactor(IVector n, IMatrix cN, GeometricProperties gps) {
        return 1.0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJacobianTransformation(br.ufmg.dees.insane.util.IVector, br.ufmg.dees.insane.util.IMatrix)
     */
    public double getJacobianTransformation(IMatrix dl, IMatrix cN) {
        IMatrix aux = new IMatrix(1,3);
        aux.mul(dl,cN);
        return Math.sqrt(Math.pow(aux.getElement(0,0),2.0)+Math.pow(aux.getElement(0,1),2.0)+Math.pow(aux.getElement(0,2),2.0));
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDominion()
     */
    public int getDominion() {
         return 3;
    }
    
	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getTransformationMatrix(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
	 */
	public IMatrix getTransformationMatrix(IMatrix dl, IMatrix cN){
		IMatrix transf = new IMatrix(dl.getNumCol()*6,dl.getNumCol()*6);
		transf.setZero();
		IMatrix r = new IMatrix(1,3);
        r.mul(dl,cN);
        double moduloR = Math.sqrt(Math.pow(r.getElement(0,0),2.0)+Math.pow(r.getElement(0,1),2.0)+Math.pow(r.getElement(0,2),2.0)); 
		double n = (r.getElement(0,2) / moduloR);
		IMatrix aux = new IMatrix(3,3);
		aux.setZero();
		
		//Setting the value of the matrix for an element whose local x axis is not parallel to the global z axis
		if (n!=1 && n!=-1) {
		    
			//Setting the value of the variable l, m, n and d
			double l = (r.getElement(0,0)/ moduloR);
			double m = (r.getElement(0,1) / moduloR);
			double d = Math.sqrt(Math.pow(l, 2) + Math.pow(m, 2));
			
			//Setting the value of the aux matrix
			aux.setElement(0, 0, l);
			aux.setElement(0, 1, m);
			aux.setElement(0, 2, n);
			aux.setElement(1, 0, -m/d);
			aux.setElement(1, 1, l/d);
			aux.setElement(2, 0, -l*n/d);
			aux.setElement(2, 1, -m*n/d);
			aux.setElement(2, 2, d);
		}
		
			//Setting the value of the matrix for an element whose positive local x axis is parallel to the global positive z axis
			else if(n==1) {
				//Setting the value of the aux matrix
				aux.setElement(0, 2, 1);
				aux.setElement(1, 1, 1);
				aux.setElement(2, 0, -1);
			}
			
			//Setting the value of the matrix for an element whose positive local x axis opposites the global positive z axis
			else {
				//Setting the value of the aux matrix
				aux.setElement(0, 2, -1);
				aux.setElement(1, 1, 1);
				aux.setElement(2, 0, 1);
				
			}

			//Inserting the aux matrix at the postions (0,0) til (dl.getNumCol()*this.getNdf()-3,dl.getNumCol()*this.getNdf()-3) of the matrix
			for (int i = 0; i < (dl.getNumCol()*6)/3; i++) {
			    aux.copySubMatrix(0, 0, 3, 3, 3*i, 3*i, transf);
            }
		return (transf);
	}

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJ2(br.ufmg.dees.insane.util.IVector)
     */
    public double getJ2(IVector s) {
        // TODO Auto-generated method stub
        return 0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdJ2dSIG(br.ufmg.dees.insane.util.IVector)
     */
    public IVector getdJ2dSIG(IVector s) {
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getJ3(br.ufmg.dees.insane.util.IVector)
     */
    public double getJ3(IVector s) {
        // TODO Auto-generated method stub
        return 0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdJ3dSIG(br.ufmg.dees.insane.util.IVector)
     */
    public IVector getdJ3dSIG(IVector s) {
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI1(br.ufmg.dees.insane.util.IVector)
     */
    public double getI1(IVector s) {
        // TODO Auto-generated method stub
        return 0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI1dSIG(br.ufmg.dees.insane.util.IVector)
     */
    public IVector getdI1dSIG(IVector s) {
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI2(br.ufmg.dees.insane.util.IVector)
     */
    public double getI2(IVector s) {
        // TODO Auto-generated method stub
        return 0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI2dSIG(br.ufmg.dees.insane.util.IVector)
     */
    public IVector getdI2dSIG(IVector s) {
        // TODO Auto-generated method stub
        return null;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getI3(br.ufmg.dees.insane.util.IVector)
     */
    public double getI3(IVector s) {
        // TODO Auto-generated method stub
        return 0;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getdI3dSIG(br.ufmg.dees.insane.util.IVector)
     */
    public IVector getdI3dSIG(IVector s) {
        // TODO Auto-generated method stub
        return null;
    }

	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#modifyInternalVariableOperator(br.ufmg.dees.insane.util.IMatrix, br.ufmg.dees.insane.util.IMatrix)
	 */
	public IMatrix modifyInternalVariableOperator(IMatrix e, IMatrix p) {
		// TODO Auto-generated method stub
		return e;
	}
	
	/* (non-Javadoc)
	 * @see br.ufmg.dees.insane.analysisModel.AnalysisModel#getDOFLabels(int)
	 */
	public ArrayList getDOFLabels(int n){
		ArrayList <PointValues> al = new ArrayList<PointValues>();
		PointValues spv = new StringPointValues();
	    spv.addPointValue("Dx");
	    spv.addPointValue("Dy");
	    spv.addPointValue("Dz");
	    spv.addPointValue("Rx");
	    spv.addPointValue("Ry");
	    spv.addPointValue("Rz");
		for(int i=0; i<n; i++) {
			al.add(i,spv);
		}
		return al;
	}

	public ArrayList getDOFLabels() {
		// TODO Auto-generated method stub
		return null;
	}

	public IMatrix getPMatrix() {
		// TODO Auto-generated method stub
		return null;
	}

}
